﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition.Hosting;

namespace System.ApplicationModel.Composition
{
    /// <summary>
    /// Helper for export management.
    /// </summary>
    public static class ExportProviderHelper
    {
        /// <summary>
        /// Gets a View matching a given export contract.
        /// </summary>
        /// <param name="provider">The export provider.</param>
        /// <param name="name">The name of the View.</param>
        /// <returns>Returns the matching View.</returns>
        /// <exception cref="System.ComponentModel.Composition.ImportCardinalityMismatchException">
        /// There are zero exported objects with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.-or-There
        /// is more than one exported object with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">The System.ComponentModel.Composition.Hosting.CompositionContainer object has been disposed of.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionContractMismatchException">The underlying exported object cannot be cast to T.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionException">An error occurred during composition. System.ComponentModel.Composition.CompositionException.Errors will contain a collection of errors that occurred.</exception>
        public static object GetView(this ExportProvider provider, string name)
        {
            if (object.ReferenceEquals(provider, null))
            {
                throw new ArgumentNullException("provider");
            }
            return provider.GetView<object>(name);
        }

        /// <summary>
        /// Gets a View matching a given export contract.
        /// </summary>
        /// <typeparam name="T">The type of the View.</typeparam>
        /// <param name="provider">The export provider.</param>
        /// <param name="name">The name of the View.</param>
        /// <returns>Returns the matching View.</returns>
        /// <exception cref="System.ComponentModel.Composition.ImportCardinalityMismatchException">
        /// There are zero exported objects with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.-or-There
        /// is more than one exported object with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">The System.ComponentModel.Composition.Hosting.CompositionContainer object has been disposed of.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionContractMismatchException">The underlying exported object cannot be cast to T.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionException">An error occurred during composition. System.ComponentModel.Composition.CompositionException.Errors will contain a collection of errors that occurred.</exception>
        public static T GetView<T>(this ExportProvider provider, string name)
        {
            if (object.ReferenceEquals(provider, null))
            {
                throw new ArgumentNullException("provider");
            }
            return provider.GetExportedValue<T>(name + "View");
        }

        /// <summary>
        /// Gets a ViewModel matching a given export contract.
        /// </summary>
        /// <param name="provider">The export provider.</param>
        /// <param name="name">The name of the ViewModel.</param>
        /// <returns>Returns the matching ViewModel.</returns>
        /// <exception cref="System.ComponentModel.Composition.ImportCardinalityMismatchException">
        /// There are zero exported objects with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.-or-There
        /// is more than one exported object with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">The System.ComponentModel.Composition.Hosting.CompositionContainer object has been disposed of.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionContractMismatchException">The underlying exported object cannot be cast to T.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionException">An error occurred during composition. System.ComponentModel.Composition.CompositionException.Errors will contain a collection of errors that occurred.</exception>
        public static object GetViewModel(this ExportProvider provider, string name)
        {
            if (object.ReferenceEquals(provider, null))
            {
                throw new ArgumentNullException("provider");
            }
            return provider.GetView<object>(name);
        }

        /// <summary>
        /// Gets a ViewModel matching a given export contract.
        /// </summary>
        /// <typeparam name="T">The type of the provider.</typeparam>
        /// <param name="provider">The export provider.</param>
        /// <param name="name">The name of the ViewModel.</param>
        /// <returns>Returns the matching ViewModel.</returns>
        /// <exception cref="System.ComponentModel.Composition.ImportCardinalityMismatchException">
        /// There are zero exported objects with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.-or-There
        /// is more than one exported object with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">The System.ComponentModel.Composition.Hosting.CompositionContainer object has been disposed of.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionContractMismatchException">The underlying exported object cannot be cast to T.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionException">An error occurred during composition. System.ComponentModel.Composition.CompositionException.Errors will contain a collection of errors that occurred.</exception>
        public static T GetViewModel<T>(this ExportProvider provider, string name)
        {
            if (object.ReferenceEquals(provider, null))
            {
                throw new ArgumentNullException("provider");
            }
            return provider.GetExportedValue<T>(name + "ViewModel");
        }

        /// <summary>
        /// Gets the shell View.
        /// </summary>
        /// <param name="provider">The export provider.</param>
        /// <returns>Returns the shell view.</returns>
        /// <exception cref="System.ComponentModel.Composition.ImportCardinalityMismatchException">
        /// There are zero exported objects with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.-or-There
        /// is more than one exported object with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">The System.ComponentModel.Composition.Hosting.CompositionContainer object has been disposed of.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionContractMismatchException">The underlying exported object cannot be cast to T.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionException">An error occurred during composition. System.ComponentModel.Composition.CompositionException.Errors will contain a collection of errors that occurred.</exception>
        public static object GetShell(this ExportProvider provider)
        {
            if (object.ReferenceEquals(provider, null))
            {
                throw new ArgumentNullException("provider");
            }
            return provider.GetShell<object>();
        }

        /// <summary>
        /// Gets the shell View.
        /// </summary>
        /// <param name="provider">The export provider.</param>
        /// <param name="name">The name of the View.</param>
        /// <returns>Returns the shell view.</returns>
        /// <exception cref="System.ComponentModel.Composition.ImportCardinalityMismatchException">
        /// There are zero exported objects with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.-or-There
        /// is more than one exported object with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">The System.ComponentModel.Composition.Hosting.CompositionContainer object has been disposed of.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionContractMismatchException">The underlying exported object cannot be cast to T.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionException">An error occurred during composition. System.ComponentModel.Composition.CompositionException.Errors will contain a collection of errors that occurred.</exception>
        public static object GetShell(this ExportProvider provider, string name)
        {
            if (object.ReferenceEquals(provider, null))
            {
                throw new ArgumentNullException("provider");
            }
            return provider.GetShell<object>(name);
        }

        /// <summary>
        /// Gets the shell View.
        /// </summary>
        /// <typeparam name="T">The type of the View.</typeparam>
        /// <param name="provider">The export provider.</param>
        /// <returns>Returns the shell view.</returns>
        /// <exception cref="System.ComponentModel.Composition.ImportCardinalityMismatchException">
        /// There are zero exported objects with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.-or-There
        /// is more than one exported object with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">The System.ComponentModel.Composition.Hosting.CompositionContainer object has been disposed of.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionContractMismatchException">The underlying exported object cannot be cast to T.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionException">An error occurred during composition. System.ComponentModel.Composition.CompositionException.Errors will contain a collection of errors that occurred.</exception>
        public static T GetShell<T>(this ExportProvider provider)
        {
            if (object.ReferenceEquals(provider, null))
            {
                throw new ArgumentNullException("provider");
            }
            return provider.GetShell<T>(string.Empty);
        }

        /// <summary>
        /// Gets the shell View.
        /// </summary>
        /// <typeparam name="T">The type of the View.</typeparam>
        /// <param name="provider">The export provider.</param>
        /// <param name="name">The name of the View.</param>
        /// <returns>Returns the shell view.</returns>
        /// <exception cref="System.ComponentModel.Composition.ImportCardinalityMismatchException">
        /// There are zero exported objects with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.-or-There
        /// is more than one exported object with the contract name derived from T in
        /// the System.ComponentModel.Composition.Hosting.CompositionContainer.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">The System.ComponentModel.Composition.Hosting.CompositionContainer object has been disposed of.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionContractMismatchException">The underlying exported object cannot be cast to T.</exception>
        /// <exception cref="System.ComponentModel.Composition.CompositionException">An error occurred during composition. System.ComponentModel.Composition.CompositionException.Errors will contain a collection of errors that occurred.</exception>
        public static T GetShell<T>(this ExportProvider provider, string name)
        {
            if (object.ReferenceEquals(provider, null))
            {
                throw new ArgumentNullException("provider");
            }
            return provider.GetExportedValue<T>(name + "ShellView");
        }
    }
}
